#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
#include <list>
#include <string>
#include <string.h>
#include <algorithm>
#include <opencv2/opencv.hpp>
#if 0
#define DEBUG std::cout << endl << __FUNCTION__ << " " << __LINE__ << endl
#else
#define DEBUG
#endif

using namespace std;

bool visited[10*15] = {false};

struct Pos{
public:
    Pos(int x_,int y_)
        :x(x_),y(y_) {}
    Pos(const Pos& ref)
    {
        x = ref.x;
        y = ref.y;
    }

    int x;
    int y;
};

class Cluster_
{
public:
    Cluster_()
        :mType(0)
    {
        m_area.clear();
    }
    Cluster_(int color)
        :mType(color)
    {
        m_area.clear();
    }
    Cluster_(int color,Pos pos)
        :mType(color)
    {
        m_area.clear();
        m_area.push_back(pos);
    }
    Cluster_(const Cluster_& ref)
        :mType(ref.mType)
    {
        m_area.clear();
        for (size_t var = 0; var < ref.m_area.size(); ++var) {
            m_area.push_back(ref.m_area[var]); ;
        }
    }

    Cluster_ operator= (const Cluster_& ref)
    {
        Cluster_ cluster(ref.mType);
        cluster.m_area.clear();
        for (size_t var = 0; var < ref.m_area.size(); ++var) {
            cluster.pushPos(ref.m_area[var]); ;
        }
        return cluster;
    }

    bool operator <(Cluster_& ref)
    {
        if(m_area.size() > ref.m_area.size())
            return true;
        else if((m_area.size() == ref.m_area.size()))
        {
            std::sort(m_area.begin(),m_area.end(),[](Pos&a1, Pos& b1)->bool
            {
                if(a1.x < b1.x) return true;
                else if(a1.x==b1.x && a1.y>b1.y) return true;
                else return false;
            });
            std::sort(ref.m_area.begin(),ref.m_area.end(),[](Pos& a1, Pos& b1)->bool
            {
                if(a1.x < b1.x) return true;
                else if(a1.x==b1.x && a1.y>b1.y) return true;
                else return false;
            });

            if(m_area[0].x<ref.m_area[0].x) return true;
            else if(m_area[0].x==ref.m_area[0].x && m_area[0].y>ref.m_area[0].y) return true;
            else return false;
        }
        return false;
    }

    int pushPos(Pos pos)
    {
        m_area.push_back(pos);
    }

    friend ostream& operator <<(ostream& out,Cluster_& ref)
    {
        std::sort(ref.m_area.begin(),ref.m_area.end(),[](Pos&a, Pos& b)->bool
        {
            if(a.x < b.x) return true;
            else if(a.x==b.x && a.y>b.y) return true;
            else return false;
        });
        out << "(" << 10 - ref.m_area[0].y << "," << ref.m_area[0].x + 1 << ")";
        return out;
    }

    const int mType;
    std::vector<Pos> m_area;
};

bool compareCluter(Cluster_* a ,Cluster_* b)
{
    if(a->m_area.size() < b->m_area.size())
        return true;
    else if((a->m_area.size() == b->m_area.size()))
    {
        std::sort(a->m_area.begin(),a->m_area.end(),[](Pos&a1, Pos& b1)->bool
        {
            if(a1.y>b1.y) return true;
            else if(a1.y==b1.y && a1.x < b1.x) return true;
            else return false;
        });
        std::sort(b->m_area.begin(),b->m_area.end(),[](Pos&a1, Pos& b1)->bool
        {
            if(a1.y>b1.y) return true;
            else if(a1.y==b1.y && a1.x < b1.x) return true;
            else return false;
        });

        if(a->m_area[0].y>b->m_area[0].y) return true;
        else if(a->m_area[0].y==b->m_area[0].y && a->m_area[0].x>b->m_area[0].x) return true;
        else return false;
    }
    return false;
}

char color[3] = {'R','G','B'};

int travel(int *data)
{
    for (int row = 0; row < 10; ++row) {
        for (int col = 0; col < 15; ++col) {
            cout << color[data[row*15 + col]] << " ";
        }
        cout << endl;
    }
}

int refreshMap(int *data,Cluster_ &maxArea,int& countZero)
{
    //! 1. remove
    for(auto elem:maxArea.m_area)
    {
        data[elem.y*15 + elem.x] = -1;
    }
    //! 2. down
    {
        for (int x = 0; x < 15; ++x) {
            vector<int> newData;
            for (int y = 0; y < 10; ++y) {
                if(data[y*15+x]!=-1)
                    newData.push_back(data[y*15+x]);
            }
            int newIndex = 0;
            int yIndex = 0;
            for (; yIndex < 10 - newData.size(); ++yIndex) {
                data[yIndex*15 + x] = -1;
            }
            for (; yIndex < 10; ++yIndex,++newIndex) {
                data[yIndex*15 + x] = newData[newIndex];
            }
        }
    }

    //! 3. left
    vector<int> candidate,candidateCopy;
    bool beginCountNonZero = false;
    for (int x = 0; x < (15-countZero); ++x) {
        int count = 0;
        for (int y = 0; y < 10; ++y) {
            if(data[y*15+x]==-1) count++;
        }
        if(count==10) //! sift right cols
        {
            candidate.push_back(x);
            beginCountNonZero = true;
        }
        else if(beginCountNonZero)
        {
            candidateCopy.push_back(x);
        }
    }
    if(candidate.size()>0)
    {
        int moveCols = 15-candidate[0]-countZero-candidate.size();
        int *copyData = new int[moveCols*10];

        //!< cols first
        for (int x = 0, xCandidate = 0; x < moveCols; ++x) {
            int originX = candidateCopy[xCandidate++];
            for (int y = 0; y < 10; ++y) {
                copyData[x*10+y] = data[y*15+originX];
            }
        }

        //!< set back
        int setBackX = 0;
        for (int x = candidate[0]; x < 15-countZero; ++x) {
            for (int y = 0; y < 10; ++y) {
                if( x<(candidate[0]+candidateCopy.size()) )
                {
                    data[y*15+x] = copyData[setBackX*10+y];
                }
                else
                {
                    data[y*15+x] = -1;
                }
            }
            setBackX++;
        }

        countZero += candidate.size();
        delete []copyData;
    }
}

int solve(int *data)
{
    int maxSize = -1;
    int remain = 150;
    int totalScore = 0;
    int count_ = 0;
    //    travel(data);
    int countZero = 0;
    while (true) {
        int score = 0;
        memset(visited,false,sizeof(visited));
        list<Cluster_> areas;
        areas.clear();
        for (int row = 0; row < 10; ++row) {
            for (int col = 0; col < 15; ++col) {
                if(!visited[row*15+col] && data[row*15+col] != -1)
                {
                    visited[row*15+col] = true;
                    Cluster_ newArea(data[row*15+col],Pos(col,row));

                    std::queue<Pos> Stack;
                    Stack.push(Pos(col,row));

                    while(!Stack.empty()){
                        Pos current = Stack.front();
                        Stack.pop();
                        int x = current.x;
                        int y = current.y;
                        visited[y*15+x] = true;

                        if( ((x-1) > -1) && !visited[y*15+x-1] && (data[y*15+x-1] == data[y*15+x]) ) // left
                        {
                            visited[y*15+x-1] = true;
                            newArea.pushPos(Pos(x-1,y));
                            Stack.push(Pos(x-1,y));
                        }
                        if( ((y-1) > -1) && !visited[y*15+x-15] && (data[y*15+x-15] == data[y*15+x]) ) // up
                        {
                            visited[y*15+x-15] = true;
                            newArea.pushPos(Pos(x,y-1));
                            Stack.push(Pos(x,y-1));
                        }
                        if( ((x+1) < 15) && !visited[y*15+x+1] && (data[y*15+x+1] == data[y*15+x]) ) // right
                        {
                            visited[y*15+x+1] = true;
                            newArea.pushPos(Pos(x+1,y));
                            Stack.push(Pos(x+1,y));
                        }
                        if( ((y+1) < 10) && !visited[y*15+x+15] && (data[y*15+x+15] == data[y*15+x]) ) // down
                        {
                            visited[y*15+x+15] = true;
                            newArea.pushPos(Pos(x,y+1));
                            Stack.push(Pos(x,y+1));
                        }
                    }
                    areas.push_back(newArea);
                }
            }
        }
        areas.sort();
        maxSize = areas.front().m_area.size();

        score = (maxSize-2)*(maxSize-2);
        if(maxSize==1)
        {
            break;
        }
        else if(maxSize==remain)
        {
            totalScore += 1000;
            cout << "Move " << ++count_ << " at "<< areas.front() << ": removed "
                 << maxSize << " balls of color " << color[areas.front().mType]
                 << ", got " << score << " points.\n";
            totalScore += score;
            remain -= maxSize;
            break;
        }
        cout << "Move " << ++count_ << " at "<< areas.front() << ": removed "
             << maxSize << " balls of color " << color[areas.front().mType]
             << ", got " << score << " points.\n";

        totalScore += score;
        remain -= maxSize;
        refreshMap(data,areas.front(),countZero);
    }
    cout << "Final score: " << totalScore << ", with " << remain << " balls remaining.\n";
}

int main(int argc, char *argv[])
{
#ifdef USE_CIN_RDBUF
    ifstream inf("data.txt");
    streambuf *cinbackup;
    cinbackup = cin.rdbuf();
    cin.rdbuf(inf.rdbuf());
#endif
    int Number = 0;
    cin >> Number;
    int count = Number;
    char color;
    int data[10*15];
    while(Number--)
    {
        for (int row = 0; row < 10; ++row) {
            for (int col = 0; col < 15; ++col) {
                cin >> color;
                switch (color) {
                case 'R':
                    data[row*15 + col] = 0;
                    break;
                case 'G':
                    data[row*15 + col] = 1;
                    break;
                case 'B':
                    data[row*15 + col] = 2;
                    break;
                default:
                    cout << color << "\n\n";
                    break;
                }
            }
        }
        cout << "Game " << count-Number << ":\n\n";
        solve(data);
        cout << endl << endl;
    }
#ifdef USE_CIN_RDBUF
    cin.rdbuf(cinbackup);
    cin>>color;
#endif
    return 0;
}
